#!/usr/bin/perl -w

use utf8;
use Wx 0.15 qw[:allclasses];
use strict;
use warnings;
use Data::Dumper;

package MyIntegratorFrame;

use Wx qw[:everything];
use Wx::Event qw(EVT_BUTTON);
use threads;
use Cwd qw(getcwd);
use File::Basename qw(dirname);
use Config::Tiny;
use Core::Reportation qw(read_json general_report psite_report);
use Core::Integration qw(integrate);
use Core::IntegratorFrame;

use base qw(IntegratorFrame);

my @wins = q(xls_dir xls_file mgf_dir mgf_file json_dir json_file fasta_dir fasta_file);
my $config_file = "integrator.ini";

sub new {
	my $class = shift;
	my $self = $class->SUPER::new();
	$self->SetTitle("Integrator 3.3 The Next Generation and Beyond");

	foreach (@wins){$self->{$_} = undef}

	$self->{config_file} = $config_file;

	EVT_BUTTON($self, $self->{bt_sq_add}, \&get_sequest);
	EVT_BUTTON($self, $self->{bt_sq_clr}, \&erase_sequest );
	EVT_BUTTON($self, $self->{bt_om_add}, \&get_omssa);
	EVT_BUTTON($self, $self->{bt_om_clr}, \&erase_omssa);
	EVT_BUTTON($self, $self->{bt_ph_add}, \&get_phenyx);
	EVT_BUTTON($self, $self->{bt_ph_clr}, \&erase_phenyx);

	EVT_BUTTON($self, $self->{bt_mgf}, \&mgfsdir );
	EVT_BUTTON($self, $self->{bt_fasta}, \&get_fasta);
	EVT_BUTTON($self, $self->{bt_out}, \&set_json );
	EVT_BUTTON($self, $self->{bt_integrate}, \&integrator );

	EVT_BUTTON($self, $self->{bt_json}, \&get_json );
	EVT_BUTTON($self, $self->{bt_gen}, \&reporting );

	EVT_BUTTON($self, $self->{bt_edit}, \&edit_config);
	EVT_BUTTON($self, $self->{bt_refresh}, \&refresh_config_panel);

	$self->init_conf();

	bless($self, $class); # reconsecrate
	return $self;
}


sub get_sequest{
	my ($self, $event) = @_;
	$self->{txt} = "Select a Sequest xls file";
	$self->get_files("lbx_sq");
}

sub get_omssa{
	my ($self, $event) = @_;
	$self->{txt} = "Select a OMSSA xls file";
	$self->get_files("lbx_om");
}

sub get_phenyx{
	my ($self, $event) = @_;
	$self->{txt} = "Select a Phenyx xls file";
	$self->get_files("lbx_ph");
}

sub get_files{
	my ($self, $win) = @_;
	$self->{xls_dir} = getcwd unless defined $self->{xls_dir};
	$self->{xls_file} = "" unless defined $self->{xls_file};
	my $dialog = Wx::FileDialog->new
						($self, $self->{txt}, $self->{xls_dir}, $self->{xls_file},
						"xls (*.xls, *.xls)|*.xls*|All files (*.*)|*.*",
						wxFD_MULTIPLE,
						);

	if ($dialog->ShowModal == wxID_OK ) {
		my @paths = $dialog->GetPaths;
		$self->{xls_dir} = dirname($paths[0]);
		$self->{xls_file} = $paths[0];
		$self->{$win}->InsertItems(\@paths, 0);
	}
	$dialog->Destroy;
}

sub erase_sequest{
	my ($self, $event) = @_;
	$self->{lbx_sq}->Clear;
}

sub erase_omssa{
	my ($self, $event) = @_;
	$self->{lbx_om}->Clear;
}

sub erase_phenyx{
	my ($self, $event) = @_;
	$self->{lbx_ph}->Clear;
}

sub get_fasta{
	my ($self, $event) = @_;
	$self->{fasta_dir} = getcwd unless defined $self->{fasta_dir};
	$self->{fasta_file} = "" unless defined $self->{fasta_file};
	my $dialog = Wx::FileDialog->new
			   ($self, "Select a Fasta database",
				$self->{fasta_dir}, $self->{fasta_file},
				"fasta (*.fasta, *.Fasta)|*.fasta|All files (*.*)|*.*", wxFD_OPEN);

	if( $dialog->ShowModal == wxID_OK ) {
		my @paths = $dialog->GetPaths;
		$self->{fasta_dir} = dirname($paths[0]);
		$self->{fasta_file} = $paths[0];
		$self->{tc_fasta}->SetValue($paths[0]);
	}
	$dialog->Destroy;
}

sub set_json{
	my ($self, $event) = @_;
	$self->open_json("Select a Json out file", "tc_out", wxFD_SAVE);
}

sub get_json{
	my ($self, $event) = @_;
	$self->open_json("Select a Json database file", "tc_json", wxFD_OPEN);
}


sub open_json{
	my ($self, $txt, $win, $mode) = @_;
	$self->{json_dir} = getcwd unless defined $self->{json_dir};
	$self->{json_file} = "" unless defined $self->{json_file};
	my $dialog = Wx::FileDialog->new
					($self, $txt, $self->{json_dir}, $self->{json_file},
					"db (*.db, *.DB)|*.db|All files (*.*)|*.*", $mode);

	if( $dialog->ShowModal == wxID_OK ) {
		my @paths = $dialog->GetPaths;
		$self->{json_dir} = dirname($paths[0]);
		$self->{json_file} = $paths[0];
		$self->{$win}->SetValue($paths[0]);
	}
	$dialog->Destroy;
}


sub mgfsdir{
	my ($self, $event ) = @_;

	unless (defined($self->{mgf_dir})){
		if ($self->{xls_dir}){
			$self->{mgf_dir} = $self->{xls_dir};
		}
		else{
			$self->{mgf_dir} = getcwd;
		}
	}

	my $dialog = Wx::DirDialog->new(
				 $self, 'Select the path where the mgf files are located',
				 $self->{mgf_dir});

	if( $dialog->ShowModal == wxID_OK ) {
	  my $path = $dialog->GetPath;
	  $self->{mgf_dir} = $path;
	  $self->{tc_mgf}->Clear;
	  $self->{tc_mgf}->AppendText($path);
	}
	$dialog->Destroy;
}


sub integrator{
	my ($self, $event) = @_;

	my $mgfs_dir = $self->{tc_mgf}->GetValue();
	my @mgfs;
	opendir(my $DIR, $mgfs_dir) or die "can not open $!";
	while (defined(my $file = readdir($DIR))) {
		if ($file =~ /\.mgf$/){
			$file = $mgfs_dir . '\\' . $file;
			push @mgfs, $file;
		}
	}
	closedir($DIR);
	my $scan_method = $self->{rbx_smeth}->GetSelection;
	my @sequest = $self->{lbx_sq}->GetStrings;
	my @omssa = $self->{lbx_om}->GetStrings;
	my @phenyx = $self->{lbx_ph}->GetStrings;
	my $fasta = $self->{tc_fasta}->GetValue;
	my $json = $self->{tc_out}->GetValue;
	my $is_tmt_or_itraq = $self->{rbx_qmeth}->GetStringSelection;
	my $offset = $self->{mass_offset};
	my $precision =	$self->{mass_precision};
	my $experiment = $self->{tc_exp}->GetValue;

	my $num_engines = 0;
	my $last_engine = "";

	print "Sequest========\n";
	foreach(@sequest){
		print $_, "\n";
	}
	if($#sequest > -1){
		$num_engines++;
		$last_engine = "sequest";
	}
	print "Omssa========\n";
	foreach(@omssa){
		print $_, "\n";
	}
	if($#omssa > -1){
		$num_engines++;
		$last_engine = "omssa";
	}
	print "Phenyx========\n";
	foreach(@phenyx){
		print $_, "\n";
	}
	if($#phenyx > -1){
		$num_engines++;
		$last_engine = "phenyx";
	}
	print "========\n";
	my $one_engine = "";
	if($num_engines == 1){
		$one_engine = $last_engine;
	}
	print "Fasta DB: $fasta\n";
	print "Json output DB: $json\n";
	print "Experiment: $experiment\n";

	my $thrd = threads->create(\&integrate, \@phenyx, \@sequest, \@omssa,
								$fasta, \@mgfs, $json, $one_engine,
								$scan_method, $is_tmt_or_itraq,
								$offset, $precision, $experiment);

	return 1;
}


sub reporting {
	my ($self, $event) = @_;
	my $json_file = $self->{tc_json}->GetValue;
	my $extended_report = $self->{cbx_exrep}->GetValue;
	my $psite_report = $self->{cbx_prep}->GetValue;
	my $limit_ascore = $self->{tc_asc}->GetValue;

	unless($limit_ascore){$limit_ascore = 0;}
	my $t0 = time();

	my $out_file = $json_file;
	$out_file =~ s/\.db$//;

	my $jsondata_ref = read_json($json_file);
	my %jsondata = %{$jsondata_ref};

	#Detect  if quantification is iTRAQ or TMT.
	my $is_tmt_or_itraq = "none";
	foreach my $spectrum(keys %jsondata){
		if($jsondata{$spectrum}{'consensus_mod'} =~ /214/){
			$is_tmt_or_itraq = "itraq";
			last;
		}
		elsif($jsondata{$spectrum}{'consensus_mod'} =~ /737/){
			$is_tmt_or_itraq = "tmt";
			last;
		}
	}

	if($extended_report){
		general_report($jsondata_ref, $out_file, $limit_ascore, $is_tmt_or_itraq);
		}
	if($psite_report){
		psite_report($jsondata_ref, $out_file, $limit_ascore, $is_tmt_or_itraq);
		}

	my $tt = time() - $t0;

	print $tt, " seconds\n";
	print "======================\n";
	print " Reporting complete\n";
	print "======================\n";
}


sub init_conf{
	my $self = shift;
	$self->{lb_thisfile_val}->SetLabel($self->{config_file});

	# Create a config
	my $Config = Config::Tiny->new;
	# Open the config
	$Config = Config::Tiny->read( $self->{config_file} );

	#files and directories
	$self->{xls_dir} = $Config->{_}->{xlsdir};
	$self->{mgf_dir} = $Config->{_}->{mgfdir};
	$self->{json_dir} = $Config->{_}->{jsondir};
	$self->{fasta_file} = $Config->{_}->{fastafile};

	$self->{fasta_dir} = dirname($self->{fasta_file});

	#Quantitation
	my ($itraq_mass, $tmt_mass) = (114.1112, 126.1283);
	my $offset = $Config->{_}->{massoffset};
	my $itraq_off = $itraq_mass + $offset;
	my $tmt_off = $tmt_mass + $offset;
	my $help_mass = "iTRAQ-$itraq_mass ---> $itraq_off     TMT-$tmt_mass ---> $tmt_off";
	
	$self->{mass_offset} = $offset;
	$self->{mass_precision} = $Config->{_}->{massprecision};

	my $precision = chr(177) . " $self->{mass_precision}  uma";

	#fill integration panel
	$self->{tc_mgf}->SetValue($self->{mgf_dir});
	$self->{tc_fasta}->SetValue($self->{fasta_file});

	#fill config panel
	$self->{lb_xlsdir_val}->SetLabel($self->{xls_dir});
	$self->{lb_mgfdir_val}->SetLabel($self->{mgf_dir});
	$self->{lb_jsondir_val}->SetLabel($self->{json_dir});
	$self->{lb_fasta_val}->SetLabel($self->{fasta_file});
	$self->{lb_offset_val}->SetLabel($self->{mass_offset} . ' uma');
	$self->{lb_mass_val}->SetLabel($help_mass);
	$self->{lb_precision_val}->SetLabel($precision);
}

sub edit_config{
	my $self = shift;
	system("start $self->{config_file}");
}

sub refresh_config_panel{
	my $self = shift;
	$self->init_conf();
}




package main;
use Wx::App;

undef &Wx::App::OnInit;
*Wx::App::OnInit = sub{1};
my $app = Wx::App->new();
Wx::InitAllImageHandlers();

my $frame = MyIntegratorFrame->new();

$app->SetTopWindow($frame);
$frame->Show(1);
$app->MainLoop();

1;                         #297
